///////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#include <RSM.h>
#include <GBuffer.h>
#include <LightPoint.h>
//-----------------------------------------------------------------------------

SceneManager*
	RSMScene = NULL;
SceneManager*
	RSMScene1 = NULL;
SceneManager*
	RSMSceneLights = NULL;

//-----------------------------------------------------------------------------

Camera*
	RSMViewCamera		= NULL;
Camera*
	RSMLightCamera		= NULL;
Camera*
	RSMCamera			= NULL;

//-----------------------------------------------------------------------------

GLuint
	RSMshadowMapWidth;
GLuint
	RSMshadowMapHeight;

GBuffer
	geoBuffer;
GBuffer
	rsmBuffer;
GBuffer
	lightBuffer;

//-----------------------------------------------------------------------------

std::vector<PointLight*>	lights;
s16							lightIndex;
bool						drawLights;

//-----------------------------------------------------------------------------

std::map<std::string, f32>::iterator shaderVarsIt;
std::map<std::string, f32>	shaderVars;

//-----------------------------------------------------------------------------

void RSMLoad()
{
	shaderVars[ "lightsFact" ] = 1.0f;
	shaderVars[ "indirLightFact" ] = 1.0f;

	shaderVars[ "mrtAmbient" ] = 0.2f;
	shaderVars[ "mrtShadowLight" ] = 0.6f;

	shaderVars[ "mrtShadowOffset" ] = 0.0003f;
	shaderVars[ "mrtShadowAmp" ] = 0.2f;

	shaderVars[ "spotAng" ] = 0.93f;
	shaderVars[ "spotDecay" ] = 0.5f;

	shaderVarsIt = shaderVars.begin();

	glInfo::GetInstance()->getInfo();
	glInfo::GetInstance()->printSelf();

	RSMScene = MGL_NEW SceneManager();
	
	RSMViewCamera = RSMCamera = RSMScene->GetCamera();
	RSMCamera->moveAlongForward( 5 );
	
	RSMLightCamera = MGL_NEW Camera();
	RSMLightCamera->SetFov(45);
	RSMLightCamera->SetNear(0.1f);
	RSMLightCamera->SetFar(500.0f);

	RSMshadowMapWidth = RSMshadowMapHeight = 1024;

	std::string scene = "RSMScene2.xml";
	if( Application::GetInstance()->GetArgCount() > 1 )
	{
		for( u16 x = 1; x < Application::GetInstance()->GetArgCount(); x++ )
		{
			if( !Application::GetInstance()->GetArg( x ).compare("-s") )
			{
				x++;
				if( x < Application::GetInstance()->GetArgCount() )
				{
					scene = Application::GetInstance()->GetArg( x );
					printf("#Loading '%s'...\n",scene.c_str());
				}
			}

			if( !Application::GetInstance()->GetArg( x ).compare("-r") )
			{
				x++;
				if( x < Application::GetInstance()->GetArgCount() )
				{
					int r = atoi( Application::GetInstance()->GetArg( x ).c_str() );
					if( r > 0 && r < 10000 )
					{
						RSMshadowMapWidth = RSMshadowMapHeight = r;
						printf("#FBO Resolution = %d\n",r);
					}
				}
			}
		}
	}
	RSMScene->LoadScene( scene );

	RSMScene1 = MGL_NEW SceneManager();
	RSMScene1->LoadScene( "RSMScene1.xml" );

	RSMSceneLights = MGL_NEW SceneManager();
	
	RSMcreateFBO();

	PointLight* light = NULL;

	light = MGL_NEW PointLight();
	light->Init();
	light->SetRange( 2.0f );
	light->SetPosition( -1.0f, 3.0f, 0.0f );
	light->SetColor( 0.0f, 1.0f, 0.0f, 0.0f );
	RSMSceneLights->GetRootNode()->AddChild( light->GetObject() );
	light->Update();
	lights.push_back( light );

	light = MGL_NEW PointLight();
	light->Init();
	light->SetRange( 2.0f );
	light->SetPosition( 0.0f, 3.0f, 1.0f );
	light->SetColor( 0.0f, 0.0f, 1.0f, 0.0f );
	RSMSceneLights->GetRootNode()->AddChild( light->GetObject() );
	light->Update();
	lights.push_back( light );

	//for(u16 x = 0; x < 10; x++ )
	//{
	//	light = MGL_NEW PointLight();
	//	light->Init();
	//	light->SetRange( 2.0f );
	//	light->SetPosition( 0.0f, 2.0f, 0.0f );
	//	light->SetColor( 1.0f, 0.0f, 0.0f, 0.0f );
	//	RSMSceneLights->GetRootNode()->AddChild( light->GetObject() );
	//	light->Update();
	//	lights.push_back( light );
	//}

	lightIndex = 0;
	drawLights = false;
}

//-----------------------------------------------------------------------------

//TODO input with dt
void RSMInput()
{
	if( lights.size() )
	{
		if( InputManager::GetInstance()->KeyPressed( '/' ) )
		{
			drawLights = !drawLights;
		}
		if( InputManager::GetInstance()->KeyPressed( ',' ) )
		{
			lightIndex--;
		}
		if( InputManager::GetInstance()->KeyPressed( '.' ) )
		{
			lightIndex++;
		}
		if( lightIndex < 0 )
		{
			lightIndex = lights.size()-1;
		}
		if( lightIndex == lights.size() )
		{
			lightIndex = 0;
		}
		if( InputManager::GetInstance()->IsKeyDown( 'i' ) )
		{
			Vec3f p = lights[lightIndex]->GetPosition();
			p.z -= 0.1f;
			lights[lightIndex]->SetPosition( p.x, p.y, p.z );
		}
		if( InputManager::GetInstance()->IsKeyDown( 'k' ) )
		{
			Vec3f p = lights[lightIndex]->GetPosition();
			p.z += 0.1f;
			lights[lightIndex]->SetPosition( p.x, p.y, p.z );
		}
		if( InputManager::GetInstance()->IsKeyDown( 'j' ) )
		{
			Vec3f p = lights[lightIndex]->GetPosition();
			p.x -= 0.1f;
			lights[lightIndex]->SetPosition( p.x, p.y, p.z );
		}
		if( InputManager::GetInstance()->IsKeyDown( 'l' ) )
		{
			Vec3f p = lights[lightIndex]->GetPosition();
			p.x += 0.1f;
			lights[lightIndex]->SetPosition( p.x, p.y, p.z );
		}
		if( InputManager::GetInstance()->IsKeyDown( 'o' ) )
		{
			Vec3f p = lights[lightIndex]->GetPosition();
			p.y += 0.1f;
			lights[lightIndex]->SetPosition( p.x, p.y, p.z );
		}
		if( InputManager::GetInstance()->IsKeyDown( 'u' ) )
		{
			Vec3f p = lights[lightIndex]->GetPosition();
			p.y -= 0.1f;
			lights[lightIndex]->SetPosition( p.x, p.y, p.z );
		}
		if( InputManager::GetInstance()->KeyPressed( 'n' ) )
		{
			f32 r = lights[lightIndex]->GetRange() - 0.5f;
			if( r < 0.0f ) r = 0.0f;
			lights[lightIndex]->SetRange( r );
		}
		if( InputManager::GetInstance()->KeyPressed( 'm' ) )
		{
			f32 r = lights[lightIndex]->GetRange() + 0.5f;
			if( r > 10.0f ) r = 10.0f;
			lights[lightIndex]->SetRange( r );
		}
	}

	if( shaderVars.size() )
	{
		if( InputManager::GetInstance()->KeyPressed( 8 ) )
		{
			shaderVarsIt++;
			if( shaderVarsIt == shaderVars.end() )
			{
				shaderVarsIt = shaderVars.begin();
			}
			printf("#'%s'=%.4f\n", shaderVarsIt->first.c_str(), shaderVarsIt->second );
		}
		if( InputManager::GetInstance()->KeyPressed( '=' ) )
		{
			shaderVarsIt->second += 0.1f;
			if( shaderVarsIt->second > 1.0f ) shaderVarsIt->second = 1.0f;
			printf("#Inc '%s'=%.4f\n", shaderVarsIt->first.c_str(), shaderVarsIt->second );
		}
		if( InputManager::GetInstance()->KeyPressed( '-' ) )
		{
			shaderVarsIt->second -= 0.1f;
			if( shaderVarsIt->second < 0.0f ) shaderVarsIt->second = 0.0f;
			printf("#Dec '%s'=%.4f\n", shaderVarsIt->first.c_str(), shaderVarsIt->second );
		}
		if( InputManager::GetInstance()->KeyPressed( 13 ) )
		{
			f32 f;
			printf("#Set '%s' (%.4f) = ", shaderVarsIt->first.c_str(), shaderVarsIt->second );
			scanf("%f", &f);
			if( f >= 0.0f && f <= 1.0f )
			{
				shaderVarsIt->second = f;
				printf("#'%s'=%.4f\n", shaderVarsIt->first.c_str(), shaderVarsIt->second );
			}
		}
	}

	if( InputManager::GetInstance()->KeyPressed( '1' ) )
	{
		GPUProgram* shader = ShaderManager::GetInstance()->GetShader( "final-glsl" );;
		if( shader )
		{
			shader->SetParameter1f( "d1", 1.0f );
			shader->SetParameter1f( "d2", 0.0f );
			shader->SetParameter1f( "d3", 0.0f );
			shader->SetParameter1f( "r1", 0.0f );
			shader->SetParameter1f( "r2", 0.0f );
			shader->SetParameter1f( "r3", 0.0f );
			shader->SetParameter1f( "r4", 0.0f );
			shader->SetParameter1f( "f1", 0.0f );
			shader->SetParameter1f( "f2", 0.0f );
			shader->SetParameter1f( "f3", 0.0f );
		}
	}
	if( InputManager::GetInstance()->KeyPressed( '2' ) )
	{
		GPUProgram* shader = ShaderManager::GetInstance()->GetShader( "final-glsl" );;
		if( shader )
		{
			shader->SetParameter1f( "d1", 0.0f );
			shader->SetParameter1f( "d2", 1.0f );
			shader->SetParameter1f( "d3", 0.0f );
			shader->SetParameter1f( "r1", 0.0f );
			shader->SetParameter1f( "r2", 0.0f );
			shader->SetParameter1f( "r3", 0.0f );
			shader->SetParameter1f( "r4", 0.0f );
			shader->SetParameter1f( "f1", 0.0f );
			shader->SetParameter1f( "f2", 0.0f );
			shader->SetParameter1f( "f3", 0.0f );
		}
	}
	if( InputManager::GetInstance()->KeyPressed( '3' ) )
	{
		GPUProgram* shader = ShaderManager::GetInstance()->GetShader( "final-glsl" );;
		if( shader )
		{
			shader->SetParameter1f( "d1", 0.0f );
			shader->SetParameter1f( "d2", 0.0f );
			shader->SetParameter1f( "d3", 1.0f );
			shader->SetParameter1f( "r1", 0.0f );
			shader->SetParameter1f( "r2", 0.0f );
			shader->SetParameter1f( "r3", 0.0f );
			shader->SetParameter1f( "r4", 0.0f );
			shader->SetParameter1f( "f1", 0.0f );
			shader->SetParameter1f( "f2", 0.0f );
			shader->SetParameter1f( "f3", 0.0f );
		}
	}
	if( InputManager::GetInstance()->KeyPressed( '4' ) )
	{
		GPUProgram* shader = ShaderManager::GetInstance()->GetShader( "final-glsl" );;
		if( shader )
		{
			shader->SetParameter1f( "d1", 0.0f );
			shader->SetParameter1f( "d2", 0.0f );
			shader->SetParameter1f( "d3", 0.0f );
			shader->SetParameter1f( "r1", 1.0f );
			shader->SetParameter1f( "r2", 0.0f );
			shader->SetParameter1f( "r3", 0.0f );
			shader->SetParameter1f( "r4", 0.0f );
			shader->SetParameter1f( "f1", 0.0f );
			shader->SetParameter1f( "f2", 0.0f );
			shader->SetParameter1f( "f3", 0.0f );
		}
	}
	if( InputManager::GetInstance()->KeyPressed( '5' ) )
	{
		GPUProgram* shader = ShaderManager::GetInstance()->GetShader( "final-glsl" );;
		if( shader )
		{
			shader->SetParameter1f( "d1", 0.0f );
			shader->SetParameter1f( "d2", 0.0f );
			shader->SetParameter1f( "d3", 0.0f );
			shader->SetParameter1f( "r1", 0.0f );
			shader->SetParameter1f( "r2", 1.0f );
			shader->SetParameter1f( "r3", 0.0f );
			shader->SetParameter1f( "r4", 0.0f );
			shader->SetParameter1f( "f1", 0.0f );
			shader->SetParameter1f( "f2", 0.0f );
			shader->SetParameter1f( "f3", 0.0f );
		}
	}
	if( InputManager::GetInstance()->KeyPressed( '6' ) )
	{
		GPUProgram* shader = ShaderManager::GetInstance()->GetShader( "final-glsl" );;
		if( shader )
		{
			shader->SetParameter1f( "d1", 0.0f );
			shader->SetParameter1f( "d2", 0.0f );
			shader->SetParameter1f( "d3", 0.0f );
			shader->SetParameter1f( "r1", 0.0f );
			shader->SetParameter1f( "r2", 0.0f );
			shader->SetParameter1f( "r3", 1.0f );
			shader->SetParameter1f( "r4", 0.0f );
			shader->SetParameter1f( "f1", 0.0f );
			shader->SetParameter1f( "f2", 0.0f );
			shader->SetParameter1f( "f3", 0.0f );
		}
	}
	if( InputManager::GetInstance()->KeyPressed( '7' ) )
	{
		GPUProgram* shader = ShaderManager::GetInstance()->GetShader( "final-glsl" );;
		if( shader )
		{
			shader->SetParameter1f( "d1", 0.0f );
			shader->SetParameter1f( "d2", 0.0f );
			shader->SetParameter1f( "d3", 0.0f );
			shader->SetParameter1f( "r1", 0.0f );
			shader->SetParameter1f( "r2", 0.0f );
			shader->SetParameter1f( "r3", 0.0f );
			shader->SetParameter1f( "r4", 1.0f );
			shader->SetParameter1f( "f1", 0.0f );
			shader->SetParameter1f( "f2", 0.0f );
			shader->SetParameter1f( "f3", 0.0f );
		}
	}
	if( InputManager::GetInstance()->KeyPressed( '8' ) )
	{
		GPUProgram* shader = ShaderManager::GetInstance()->GetShader( "final-glsl" );;
		if( shader )
		{
			shader->SetParameter1f( "d1", 0.0f );
			shader->SetParameter1f( "d2", 0.0f );
			shader->SetParameter1f( "d3", 0.0f );
			shader->SetParameter1f( "r1", 0.0f );
			shader->SetParameter1f( "r2", 0.0f );
			shader->SetParameter1f( "r3", 0.0f );
			shader->SetParameter1f( "r4", 0.0f );
			shader->SetParameter1f( "f1", 1.0f );
			shader->SetParameter1f( "f2", 0.0f );
			shader->SetParameter1f( "f3", 0.0f );
		}
	}
	if( InputManager::GetInstance()->KeyPressed( '9' ) )
	{
		GPUProgram* shader = ShaderManager::GetInstance()->GetShader( "final-glsl" );;
		if( shader )
		{
			shader->SetParameter1f( "d1", 0.0f );
			shader->SetParameter1f( "d2", 0.0f );
			shader->SetParameter1f( "d3", 0.0f );
			shader->SetParameter1f( "r1", 0.0f );
			shader->SetParameter1f( "r2", 0.0f );
			shader->SetParameter1f( "r3", 0.0f );
			shader->SetParameter1f( "r4", 0.0f );
			shader->SetParameter1f( "f1", 0.0f );
			shader->SetParameter1f( "f2", 1.0f );
			shader->SetParameter1f( "f3", 0.0f );
		}
	}
	if( InputManager::GetInstance()->KeyPressed( '0' ) )
	{
		GPUProgram* shader = ShaderManager::GetInstance()->GetShader( "final-glsl" );;
		if( shader )
		{
			shader->SetParameter1f( "d1", 0.0f );
			shader->SetParameter1f( "d2", 0.0f );
			shader->SetParameter1f( "d3", 0.0f );
			shader->SetParameter1f( "r1", 0.0f );
			shader->SetParameter1f( "r2", 0.0f );
			shader->SetParameter1f( "r3", 0.0f );
			shader->SetParameter1f( "r4", 0.0f );
			shader->SetParameter1f( "f1", 0.0f );
			shader->SetParameter1f( "f2", 0.0f );
			shader->SetParameter1f( "f3", 1.0f );
		}
	}

	if( InputManager::GetInstance()->KeyPressed( '[' ) )
	{
		RSMCamera = RSMViewCamera;
	}
	if( InputManager::GetInstance()->KeyPressed( ']' ) )
	{
		RSMCamera = RSMLightCamera;
	}

	if( InputManager::GetInstance()->KeyPressed('q') )
	{
		RSMCamera->moveAlongUp( -1 );
	}
	if( InputManager::GetInstance()->KeyReleased('q') )
	{
		RSMCamera->moveAlongUp( 1 );
	}
	if( InputManager::GetInstance()->IsKeyDown('w') )
	{
		RSMCamera->moveAlongForward( -0.1f );
	}
	if( InputManager::GetInstance()->IsKeyDown('s') )
	{
		RSMCamera->moveAlongForward( 0.1f );
	}
	if( InputManager::GetInstance()->IsKeyDown('a') )
	{
		RSMCamera->moveAlongRight( -0.1f );
	}
	if( InputManager::GetInstance()->IsKeyDown('d') )
	{
		RSMCamera->moveAlongRight( 0.1f );
	}
	if( InputManager::GetInstance()->IsKeyDown('r') )
	{
		RSMCamera->moveAlongUp( 0.1f );
	}
	if( InputManager::GetInstance()->IsKeyDown('f') )
	{
		RSMCamera->moveAlongUp( -0.1f );
	}

	if( InputManager::GetInstance()->IsMouseButtonDown( 0 ) )
	{
		if( InputManager::GetInstance()->HasMouseMoved() )
		{
			if( InputManager::GetInstance()->IsMouseButtonDown( 0 ) )
			{
				RSMCamera->rotateAroundRight( InputManager::GetInstance()->GetMouseOffsetY() / 10.f );
				RSMCamera->rotateAroundY( InputManager::GetInstance()->GetMouseOffsetX() / 10.f );
			}

			if( InputManager::GetInstance()->IsMouseButtonDown( 2 ) )
			{
				RSMCamera->moveAlongForward( InputManager::GetInstance()->GetMouseOffsetY() / 100.f );
				RSMCamera->moveAlongRight( InputManager::GetInstance()->GetMouseOffsetX() / 100.f );
			}
		}
	}
}

//-----------------------------------------------------------------------------

void RSMResolutionChanged()
{
	if( RSMViewCamera ) RSMViewCamera->SetViewportSize( Application::GetInstance()->GetResolutionWidth(), Application::GetInstance()->GetResolutionHeight() );
	if( RSMLightCamera ) RSMLightCamera->SetViewportSize( Application::GetInstance()->GetResolutionWidth(), Application::GetInstance()->GetResolutionHeight() );
}

//-----------------------------------------------------------------------------

void RSMUpdate( f32 dt )
{
	GPUProgram* sh = NULL;
	sh = ShaderManager::GetInstance()->GetShader("final-glsl");
	if( sh )
	{
		sh->SetParameter1f("lightsFact", shaderVars[ "lightsFact" ]);
		sh->SetParameter1f("indirLightFact", shaderVars[ "indirLightFact" ]);
	}
	sh = ShaderManager::GetInstance()->GetShader("textured-mrt-glsl");
	if( sh )
	{
		sh->SetParameter1f("mrtAmbient", shaderVars[ "mrtAmbient" ]);
		sh->SetParameter1f("mrtShadowLight", shaderVars[ "mrtShadowLight" ]);
		sh->SetParameter1f("mrtShadowOffset", shaderVars[ "mrtShadowOffset" ]);
		sh->SetParameter1f("mrtShadowAmp", shaderVars[ "mrtShadowAmp" ]);
	}
	sh = ShaderManager::GetInstance()->GetShader("color-mrt-glsl");
	if( sh )
	{
		sh->SetParameter1f("mrtAmbient", shaderVars[ "mrtAmbient" ]);
		sh->SetParameter1f("mrtShadowLight", shaderVars[ "mrtShadowLight" ]);
		sh->SetParameter1f("mrtShadowOffset", shaderVars[ "mrtShadowOffset" ]);
		sh->SetParameter1f("mrtShadowAmp", shaderVars[ "mrtShadowAmp" ]);
	}
	sh = ShaderManager::GetInstance()->GetShader("textured-rsm-glsl");
	if( sh )
	{
		sh->SetParameter1f("spotAng", shaderVars[ "spotAng" ]);
		sh->SetParameter1f("spotDecay", shaderVars[ "spotDecay" ]);
	}
	sh = ShaderManager::GetInstance()->GetShader("color-rsm-glsl");
	if( sh )
	{
		sh->SetParameter1f("spotAng", shaderVars[ "spotAng" ]);
		sh->SetParameter1f("spotDecay", shaderVars[ "spotDecay" ]);
	}
	

	RSMViewCamera->Update( dt );
	RSMLightCamera->Update( dt );

	RSMScene->UpdateScene( dt );
	RSMScene1->UpdateScene( dt );
	RSMSceneLights->UpdateScene( dt );
}

//-----------------------------------------------------------------------------

void RSMDraw()
{
	{
		MGL_PROFILE("shadow_draw");
		RSMdrawShadow();
	}

	{
		MGL_PROFILE("geo_draw");
		RSMdrawGeo();
	}

	{
		MGL_PROFILE("lights_draw");
		RSMdrawLights();
	}

	{
		MGL_PROFILE("final_draw");
		RSMdrawFinal();
	}
}

//-----------------------------------------------------------------------------

void RSMcreateFBO()
{
	geoBuffer.init( RSMshadowMapWidth, RSMshadowMapHeight, 3, false, false );
	geoBuffer.create();

	rsmBuffer.init( RSMshadowMapWidth, RSMshadowMapHeight, 3, true, false );
	rsmBuffer.create();

	lightBuffer.init( RSMshadowMapWidth, RSMshadowMapHeight, 1, false, false );
	lightBuffer.create();

	Texture* tt = NULL;
	
	//deferred
	tt = TextureManager::GetInstance()->GetTextureOrCreate( "defColorTex" );
	tt->Load( geoBuffer.getColorTextureId( 0 ) );

	tt = TextureManager::GetInstance()->GetTextureOrCreate( "defPosTex" );
	tt->Load( geoBuffer.getColorTextureId( 1 ) );

	tt = TextureManager::GetInstance()->GetTextureOrCreate( "defNormalTex" );
	tt->Load( geoBuffer.getColorTextureId( 2 ) );

	//rsm
	tt = TextureManager::GetInstance()->GetTextureOrCreate( "rsmDepthTex" );
	tt->Load( rsmBuffer.getDepthTextureId() );

	tt = TextureManager::GetInstance()->GetTextureOrCreate( "rsmFluxTex" );
	tt->Load( rsmBuffer.getColorTextureId( 0 ) );

	tt = TextureManager::GetInstance()->GetTextureOrCreate( "rsmPosTex" );
	tt->Load( rsmBuffer.getColorTextureId( 1 ) );

	tt = TextureManager::GetInstance()->GetTextureOrCreate( "rsmNormalTex" );
	tt->Load( rsmBuffer.getColorTextureId( 2 ) );

	tt = TextureManager::GetInstance()->GetTextureOrCreate( "lightsTex" );
	tt->Load( lightBuffer.getColorTextureId( 0 ) );
}

//-----------------------------------------------------------------------------

void RSMdrawGeo()
{
	Matrix4x4 projMat, mvMat;

	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
	glClearDepth(1.0f);
	geoBuffer.begin();

	glViewport(0,0,RSMshadowMapWidth,RSMshadowMapHeight);
	glCullFace(GL_BACK);

	RSMScene->SetCamera( RSMCamera );

	//setup view
	glMatrixMode(GL_PROJECTION);
	projMat = RSMScene->GetCamera()->getProjectionMatrix();
	glLoadMatrixf( (const GLfloat*)(projMat.m) );

	glMatrixMode(GL_MODELVIEW);
	mvMat = RSMScene->GetCamera()->getViewMatrix();
	glLoadMatrixf( (const GLfloat*)(mvMat.m) );

	SettingsManager::GetInstance()->SetFlag(MGLS_RENDER_WITH_SHADOW, true);

	//draw
	glPushMatrix();

	RSMScene->DrawScene();

	if( drawLights )
	{
		RSMSceneLights->SetCamera( RSMCamera );

		//setup view
		glMatrixMode(GL_PROJECTION);
		projMat = RSMSceneLights->GetCamera()->getProjectionMatrix();
		glLoadMatrixf( (const GLfloat*)(projMat.m) );

		glMatrixMode(GL_MODELVIEW);
		mvMat = RSMSceneLights->GetCamera()->getViewMatrix();
		glLoadMatrixf( (const GLfloat*)(mvMat.m) );

		SettingsManager::GetInstance()->SetShaderPass( 1 );

		glPushMatrix();

		RSMSceneLights->DrawScene();

		glPopMatrix();

		SettingsManager::GetInstance()->SetShaderPass( 0 );
	}

	glPopMatrix();

	SettingsManager::GetInstance()->SetFlag(MGLS_RENDER_WITH_SHADOW, false);

	geoBuffer.end();
}

//-----------------------------------------------------------------------------

void RSMdrawShadow()
{
	Matrix4x4 projMat, mvMat;

	glClearDepth(1.0f);
	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
	//glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

	rsmBuffer.begin();

	glViewport(0,0,RSMshadowMapWidth,RSMshadowMapHeight);
	glCullFace(GL_BACK);
	//glCullFace(GL_FRONT);

	RSMScene->SetCamera( RSMLightCamera );

	//setup view
	glMatrixMode(GL_PROJECTION);
	projMat = RSMScene->GetCamera()->getProjectionMatrix();
	glLoadMatrixf( (const GLfloat*)(projMat.m) );

	glMatrixMode(GL_MODELVIEW);
	mvMat = RSMScene->GetCamera()->getViewMatrix();
	glLoadMatrixf( (const GLfloat*)(mvMat.m) );

	//SettingsManager::GetInstance()->SetFlag(MGLS_RENDER_DEPTH, true);
	SettingsManager::GetInstance()->SetShaderPass( 1 );

	//draw
	glPushMatrix();

	RSMScene->DrawScene();

	glPopMatrix();
	//SettingsManager::GetInstance()->SetFlag(MGLS_RENDER_DEPTH, false);
	SettingsManager::GetInstance()->SetShaderPass( 0 );

	rsmBuffer.end();

	Matrix4x4 shadowMatrix;
	shadowMatrix.SetIdentity();
	shadowMatrix.Scale( 0.5f, 0.5f, 0.5f );
	shadowMatrix.SetPosition( 0.5f, 0.5f, 0.5f );
	shadowMatrix = mvMat * projMat * shadowMatrix;

	SettingsManager::GetInstance()->SetShadowMatrix( shadowMatrix );
}

//-----------------------------------------------------------------------------

void RSMdrawLights()
{
	Matrix4x4 projMat, mvMat;

	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
	glClearDepth(1.0f);
	glClearColor(0, 0, 0, 0);

//	glDisable(GL_CULL_FACE);
	glCullFace(GL_FRONT);
	glDisable(GL_DEPTH_TEST);
	glEnable(GL_BLEND);
	glBlendFunc(GL_ONE,GL_ONE);

	lightBuffer.begin();

	glViewport(0,0,RSMshadowMapWidth,RSMshadowMapHeight);

	RSMSceneLights->SetCamera( RSMCamera );

	//setup view
	glMatrixMode(GL_PROJECTION);
	projMat = RSMSceneLights->GetCamera()->getProjectionMatrix();
	glLoadMatrixf( (const GLfloat*)(projMat.m) );

	glMatrixMode(GL_MODELVIEW);
	mvMat = RSMSceneLights->GetCamera()->getViewMatrix();
	glLoadMatrixf( (const GLfloat*)(mvMat.m) );

	//draw
	glPushMatrix();

	//light1.Render();
	RSMSceneLights->DrawScene();

	glPopMatrix();

	lightBuffer.end();

	glDisable(GL_BLEND);
	//glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);
	glEnable(GL_DEPTH_TEST);
}

//-----------------------------------------------------------------------------

void RSMdrawFinal()
{
	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 
	glClearDepth(1.0f);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

	glCullFace(GL_BACK);

	// adjust viewport and projection matrix to texture dimension
	glViewport(0, 0, Application::GetInstance()->GetResolutionWidth(), Application::GetInstance()->GetResolutionHeight());

	//setup view
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glPushMatrix();

	RSMScene1->DrawScene();

	glPopMatrix();
}

//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
